Javascript Network Requests
Fetch
Fetch function send GET request by default, but you can modify the options to submit POST.
let promise = fetch(url, [options]);
// Example
let response = await fetch(url);
// If http status is between 200-299
if(response.ok){
let json = await response.json();
}
else{
console.log("Error");
}
- Fetch returns a
promiseobject, we can check the http status for success or failure of the request. response.okreturnstrueif the http status code is 200-299- Once we get the response, we can decode the body using various formats.
response.json()
response.text()
response.formData()
response.blob()
response.arrayBuffer()
Parsing Fetched Example
function jsonInfo(data) {
const results = []; // [{ path, type, value }]
const seen = new WeakSet(); // guard against cycles
const stack = [[data, []]]; // [node, pathArray]
while (stack.length) {
const [node, path] = stack.pop();
// null is typeof 'object' but not traversable
if (node !== null && typeof node === 'object') {
if (seen.has(node)) continue;
seen.add(node);
if (Array.isArray(node)) {
// push array items with indices
for (let i = node.length - 1; i >= 0; i--) {
stack.push([node[i], path.concat(`[${i}]`)]);
}
} else {
// push object properties
const keys = Object.keys(node);
for (let i = keys.length - 1; i >= 0; i--) {
const k = keys[i];
stack.push([node[k], path.concat(k)]);
}
}
} else {
// leaf: record its path, type, and value (optional: trim long values)
results.push({
path: path.join('.').replace(/\.\[/g, '['), // pretty paths like a.b[0].c
type: node === null ? 'null' : typeof node,
value: node
});
}
}
return results;
}
(async () => {
const res = await fetch("https://microsoftedge.github.io/Demos/json-dummy-data/64KB.json");
const data = await res.json();
console.table(jsonInfo(data).slice(0, 20)); // preview first 20 paths
})();
Form Data
Form data object
formData.append(name, value)
formData.append(name, blob, fileName)
formData.set(name, value)
formData.set(name, blob, fileName)
formData.delete(name)
formData.get(name)
formData.has(name)
<form id="exampleForm">
<input type="text" name="name" value="myname">
<input type="file" name="image" value="image/*">
<input type="submit">
</form>
<script>
exampleForm.onsubmit = async(event) => {
event.preventDefault(); // refresh
let response = await fetch("API", {
method: 'POST',
body: new FormData(exampleForm);
});
let result = await response.json();
console.log(result.message);
};
</script>
Download progress (TODO: Come back to fix this)
use response.body to track download progress, ReadableStream is a special object that provides info chunk by chunk
The original JS Info example use Content-Length to get the total size, but github use gzip compressed transfer which makes the received length much longer than the transfer size.
When the server uses Content-Encoding: gzip (or br, deflate, etc.):
-
Content-Length refers to the compressed payload size on the wire.
-
But the Fetch/XHR APIs give you the decompressed stream (so you read more bytes than Content-Length indicates).
-
Or the server may omit Content-Length entirely and send with Transfer-Encoding: chunked. In that case there’s no declared total size.
So if you rely blindly on Content-Length for progress:
-
You can show wrong percentages (e.g. progress bar hits 100% while still downloading more).
-
Or you get null (no header at all), leaving you with only bytes-so-far.
Fetch: Abort
AbortController can be used with fetch to signal abort.
let controller = new AbortController();
let signal = controllere